package util

import (
	"database/sql"
	"fmt"
	"reflect"
)

// MapMerge 合并多个map到一个新的map中
func MapMerge[KT comparable, VT any](maps ...map[KT]VT) map[KT]VT {
	// 创建一个新的map用于存储合并后的结果
	result := make(map[KT]VT)

	// 遍历所有传入的map
	for _, m := range maps {
		// 遍历当前map的每个键值对
		for k, v := range m {
			// 将键值对添加到结果map中
			result[k] = v
		}
	}
	return result
}

// MapKeys 获取map的key到一个切片中
func MapKeys[KT comparable, VT any](m map[KT]VT) []KT {
	result := make([]KT, 0, len(m))
	for k := range m {
		result = append(result, k)
	}
	return result
}

// 获取map的指定key值，不满足条件则返回默认值
func MapKeyValue[KT comparable, VT any](m map[KT]any, k KT, def VT) VT {
	v, exists := m[k]
	if !exists {
		return def
	}
	value, ok := v.(VT)
	if !ok {
		return def
	}
	return value
}

// 获取map的指定key值的string值，不满足条件则返回默认值
func MapStrValue[KT comparable](m map[KT]any, k KT, def ...string) (value string) {
	if v, exists := m[k]; exists {
		if val, err := ToString(v); err == nil {
			value = val
			return
		}
	}
	if len(def) > 0 {
		value = def[0]
	}
	return
}

// 获取map的指定key值的int值，不满足条件则返回默认值
func MapIntValue[KT comparable](m map[KT]any, k KT, def ...int) (value int) {
	if v, exists := m[k]; exists {
		if val, err := ToInt(v); err == nil {
			value = val
			return
		}
	}
	if len(def) > 0 {
		value = def[0]
	}
	return
}

// 获取map的指定key值的uint8值，不满足条件则返回默认值
func MapUint8Value[KT comparable](m map[KT]any, k KT, def ...uint8) (value uint8) {
	if v, exists := m[k]; exists {
		if val, err := ToUint8(v); err == nil {
			value = val
			return
		}
	}
	if len(def) > 0 {
		value = def[0]
	}
	return
}

// 获取map的指定key值的uint64值，不满足条件则返回默认值
func MapUint64Value[KT comparable](m map[KT]any, k KT, def ...uint64) (value uint64) {
	if v, exists := m[k]; exists {
		if val, err := ToUint64(v); err == nil {
			value = val
			return
		}
	}
	if len(def) > 0 {
		value = def[0]
	}
	return
}

// MapToStruct 将 map 的键值赋值到结构体属性中
// 如：MapToStruct(data, &person)
func MapToStruct(m map[string]interface{}, s interface{}) error {
	// 获取结构体的反射值和类型
	structValue := reflect.ValueOf(s)

	// 处理指针
	if structValue.Kind() == reflect.Ptr {
		if structValue.IsNil() {
			return fmt.Errorf("方法 MapToStruct 目标对象是一个空指针")
		}
		structValue = structValue.Elem()
	}

	if structValue.Kind() != reflect.Struct {
		return fmt.Errorf("方法 MapToStruct 目标对象不是一个结构体")
	}

	structType := structValue.Type()

	// 遍历结构体的每个字段
	for i := 0; i < structValue.NumField(); i++ {
		field := structValue.Field(i)
		fieldType := structType.Field(i)

		// 跳过不可设置的字段
		if !field.CanSet() {
			continue
		}

		// 获取 json 标签的值
		jsonTag := fieldType.Tag.Get("json")
		if jsonTag == "" {
			continue
		}

		// 检查 map 中是否存在对应的键
		if value, exists := m[jsonTag]; exists {
			if value == nil {
				// 处理 nil 值
				if field.Kind() == reflect.Ptr {
					if !field.IsNil() {
						field.Set(reflect.Zero(field.Type()))
					}
				} else {
					field.Set(reflect.Zero(field.Type()))
				}
				continue
			}

			// 处理结构体字段
			if field.Kind() == reflect.Struct {
				if err := mapToStructHandleStructField(value, field); err != nil {
					fmt.Printf("方法 MapToStruct 字段%s映射处理异常！%v\r\n", fieldType.Name, err)
				}
				continue
			}

			// 处理指针类型的结构体字段
			if field.Kind() == reflect.Ptr && field.Type().Elem().Kind() == reflect.Struct {
				if field.IsNil() {
					field.Set(reflect.New(field.Type().Elem()))
				}
				if err := mapToStructHandleStructField(value, field.Elem()); err != nil {
					fmt.Printf("方法 MapToStruct 字段%s映射处理异常！%v\r\n", fieldType.Name, err)
				}
				continue
			}

			// 处理 sql.Scanner 接口
			if fieldType.Type.PkgPath() != "" {
				if scanner, ok := field.Addr().Interface().(sql.Scanner); ok {
					err := scanner.Scan(value)
					if err != nil {
						fmt.Printf("方法 MapToStruct 字段%s调用Scan方法异常！%v\r\n", fieldType.Name, err)
					}
					continue
				}
			}

			// 处理其他类型
			valueReflect := reflect.ValueOf(value)
			if valueReflect.Type().AssignableTo(field.Type()) {
				field.Set(valueReflect)
				continue
			}

			// 尝试类型转换
			if convertedValue, err := mapToStructConvertValue(value, field.Type()); err == nil {
				field.Set(convertedValue)
			} else {
				fmt.Printf("方法 MapToStruct 字段%s映射值类型转换异常！%v\n", fieldType.Name, err)
			}
		}
	}

	return nil
}

// 处理结构体字段
func mapToStructHandleStructField(value interface{}, field reflect.Value) error {
	// 确保值是 map 类型
	valueMap, ok := value.(map[string]interface{})
	if !ok {
		return fmt.Errorf("字段映射类型不匹配，映射值类型为：%T", value)
	}

	// 递归调用 MapToStruct
	return MapToStruct(valueMap, field.Addr().Interface())
}

// 尝试将值转换为目标类型
func mapToStructConvertValue(value interface{}, targetType reflect.Type) (reflect.Value, error) {
	valueReflect := reflect.ValueOf(value)

	// 处理基本类型转换
	switch targetType.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if v, ok := value.(int8); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(int16); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(int32); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(int); ok {
			return reflect.ValueOf(int64(v)).Convert(targetType), nil
		}
		if v, ok := value.(int64); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(float64); ok {
			return reflect.ValueOf(int64(v)).Convert(targetType), nil
		}

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if v, ok := value.(uint8); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(uint16); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(uint32); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(uint); ok {
			return reflect.ValueOf(uint64(v)).Convert(targetType), nil
		}
		if v, ok := value.(uint64); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(float64); ok {
			return reflect.ValueOf(uint64(v)).Convert(targetType), nil
		}

	case reflect.Float32, reflect.Float64:
		if v, ok := value.(float64); ok {
			return reflect.ValueOf(v).Convert(targetType), nil
		}
		if v, ok := value.(int); ok {
			return reflect.ValueOf(float64(v)).Convert(targetType), nil
		}

	case reflect.String:
		if v, ok := value.(string); ok {
			return reflect.ValueOf(v), nil
		}
		return reflect.ValueOf(fmt.Sprintf("%v", value)), nil

	case reflect.Slice:
		if valueReflect.Kind() == reflect.Slice {
			slice := reflect.MakeSlice(targetType, valueReflect.Len(), valueReflect.Len())
			elemType := targetType.Elem()

			for i := 0; i < valueReflect.Len(); i++ {
				elemValue := valueReflect.Index(i).Interface()
				if converted, err := mapToStructConvertValue(elemValue, elemType); err == nil {
					slice.Index(i).Set(converted)
				} else {
					return reflect.Value{}, fmt.Errorf("无法转换索引%d处的切片元素: %v", i, err)
				}
			}

			return slice, nil
		}
	}

	return reflect.Value{}, fmt.Errorf("不支持将类型%T转换为目标类型%s", value, targetType)
}
